package com.fjwt.gz.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.fjwt.gz.db.entity.StatScoreNumDayEntity;
import com.fjwt.gz.db.vo.StatScoreNumDayVO;
import com.fjwt.gz.service.mapper.StatScoreNumDayMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 统计：机构积分统计日表 服务实现类
 * </p>
 *
 * @author shiyonghao
 * @since 2025-07-24
 */
@Slf4j
@Service
public class StatScoreNumDayService extends ServiceImpl<StatScoreNumDayMapper, StatScoreNumDayEntity> {

    @Autowired
    private StatScoreRecordService statScoreRecordService;

    private static final String STAT_TYPE_MONTH = "day";
    private static final int BATCH_SIZE = 1000;
    // 首页柱形图统计天数
    static final int STAT_DAY = 15;


    public void getScoreNumDayStatistics(DateTime yesterday) {

        String time = DateUtil.format(yesterday, "yyyyMMdd");
        // 总体福分统计
        List<StatScoreNumDayVO> records = statScoreRecordService.getScoreNumDayOrMonthStatistics(STAT_TYPE_MONTH, time);
        // 统计迁移福分
        List<StatScoreNumDayVO> syncScoreDay = statScoreRecordService.getSyncScoreNumDayOrMonthStatistics(STAT_TYPE_MONTH, time);
        if (records.isEmpty()) {
            return;
        }

        // 3. 转换数据格式
        List<StatScoreNumDayEntity> statisticsList = convertToStatistics(records, syncScoreDay);

        // 4. 批量插入统计表
        saveBatchStatistics(statisticsList);
    }

    private List<StatScoreNumDayEntity> convertToStatistics(List<StatScoreNumDayVO> records, List<StatScoreNumDayVO> syncScoreDay) {
        List<StatScoreNumDayEntity> result = new ArrayList<>();
        Map<String, StatScoreNumDayVO> map = new HashMap<>();
        if (CollUtil.isNotEmpty(syncScoreDay)) {
            //通过机构号分
            map = syncScoreDay.stream()
                    .filter(vo -> ObjectUtils.isNotEmpty(vo.getAgentNo()) && !"0".equals(vo.getAgentNo()))
                    .collect(Collectors.toMap(StatScoreNumDayVO::getAgentNo, entity -> entity));
        }

        for (StatScoreNumDayVO record : records) {
            StatScoreNumDayEntity stat = new StatScoreNumDayEntity();

            // 处理迁移福分
            StatScoreNumDayVO syncData = map.get(record.getAgentNo());
            stat.setDaySyncScoreNum(syncData != null ? syncData.getDaySyncScoreNum() : 0L)
                    .setTotalSyncScoreNum(syncData != null ? syncData.getTotalSyncScoreNum() : 0L);

            // 机构
            switch (record.getAgentLevel()) {
                case 1: stat.setAgentNo(record.getAgentNo1()); break;
                case 2: stat.setAgentNo(record.getAgentNo2()); break;
                case 3: stat.setAgentNo(record.getAgentNo3()); break;
                case 4: stat.setAgentNo(record.getAgentNo4()); break;
                default: stat.setAgentNo("0"); break;
            }

            // 直接映射字段
            stat.setLiteAppId(record.getLiteAppId())
                    .setAgentScoreId(record.getAgentScoreId())
                    .setStatDate(DateUtil.yesterday())
                    .setTotalUnusedScoreNum(record.getTotalScoreNum() - record.getTotalUsedScoreNum())
                    .setTotalUsedScoreNum(record.getTotalUsedScoreNum())
                    .setTotalOverScoreNum(record.getTotalOverScoreNum())
                    .setDayAddScoreNum(record.getDayAddScoreNum())
                    .setDayUsedScoreNum(record.getDayUsedScoreNum())
                    .setDayOverScoreNum(record.getDayOverScoreNum())
                    .setDayAddBaifuScoreNum(record.getDayAddBaifuScoreNum())
                    .setDayExchangeCouponScoreNum(record.getDayExchangeCouponScoreNum())
                    .setAgentNo1(record.getAgentNo1())
                    .setAgentName1(record.getAgentName1())
                    .setAgentNo2(record.getAgentNo2())
                    .setAgentName2(StrUtil.isNotBlank(record.getAgentName2()) ? record.getAgentName2() : "")
                    .setAgentNo3(record.getAgentNo3())
                    .setAgentName3(StrUtil.isNotBlank(record.getAgentName3()) ? record.getAgentName3() : "")
                    .setAgentNo4(record.getAgentNo4())
                    .setAgentName4(StrUtil.isNotBlank(record.getAgentName4()) ? record.getAgentName4() : "");



            result.add(stat);
        }

        return result;
    }

    private void saveBatchStatistics(List<StatScoreNumDayEntity> list) {
        // 使用Mybatis-Plus批量插入
        int total = list.size();

        for (int i = 0; i < total; i += BATCH_SIZE) {
            int end = Math.min(i + BATCH_SIZE, total);
            List<StatScoreNumDayEntity> subList = list.subList(i, end);
            baseMapper.insert(subList);
        }
    }

    /**
     * 获取最近一周的统计数据
     *
     * @param agentNo 机构号
     * @return
     */
    public JSONObject getDayScoreStatistics(String agentNo) {
        //根据机构号查询最近一周的统计结果
        List<StatScoreNumDayEntity> list = baseMapper.selectList(StatScoreNumDayEntity.gw()
                .eq(StrUtil.isNotBlank(agentNo), StatScoreNumDayEntity::getAgentNo, agentNo)
                .eq(StrUtil.isBlank(agentNo), StatScoreNumDayEntity::getAgentNo2, "0")
                .orderByDesc(StatScoreNumDayEntity::getStatDate)
                .last(" limit " + STAT_DAY));
        JSONObject result = new JSONObject();
        if (CollUtil.isNotEmpty(list)) {
            list = list.stream().sorted(Comparator.comparing(StatScoreNumDayEntity::getStatDate)).toList();
            //获取最近一周的日期，格式为MM-dd
            List<String> dateList = list.stream().map(item -> DateUtil.format(item.getStatDate(), "MM-dd")).toList();
            //获取最近一周的总待使用积分数
            List<Long> unusedScoreNumList = list.stream().map(StatScoreNumDayEntity::getTotalUnusedScoreNum).toList();
            //获取最近一周的总已使用积分数
            List<Long> usedScoreNumList = list.stream().map(StatScoreNumDayEntity::getTotalUsedScoreNum).toList();
            result.put("unusedScoreNumList", unusedScoreNumList);
            result.put("usedScoreNumList", usedScoreNumList);
            result.put("dateList", dateList);
        }else {
            result.put("unusedScoreNumList", new int[STAT_DAY]);
            result.put("usedScoreNumList", new int[STAT_DAY]);
            List<String> dateList = new ArrayList<>();
            DateTime date = DateUtil.date();
            for (int i = STAT_DAY; i > 0; i--) {
                dateList.add(DateUtil.format(DateUtil.offsetDay(date, -i), "MM-dd"));
            }
            result.put("dateList", dateList);
        }
        return result;
    }

    public StatScoreNumDayEntity getOverviewStatisticsByAgentNo(String agentNo) {
        StatScoreNumDayEntity entity = getOne(StatScoreNumDayEntity.gw()
                .eq(StrUtil.isNotBlank(agentNo), StatScoreNumDayEntity::getAgentNo, agentNo)
                .orderByAsc(StatScoreNumDayEntity::getAgentNo)
                .orderByDesc(StatScoreNumDayEntity::getStatDate)
                .last(" limit 1 "));
        return entity == null ? new StatScoreNumDayEntity().setTotalUnusedScoreNum(0L).setTotalUsedScoreNum(0L) : entity;
    }
}
